package com.naiterui.ehp.bs.im.repository.mongo;

import com.naiterui.ehp.bs.im.network.protocl.SessionDetails;
import com.naiterui.ehp.bs.im.network.protocl.SessionParams;
import com.naiterui.ehp.bs.im.vo.SessionConditionCountVO;
import com.naiterui.ehp.bs.im.vo.SessionConditionVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import java.util.List;

/**
 * @author He Qiang
 * @since 1.0.0
 */
@Repository
public class SessionDao extends MongoBaseDao {

    /**
     * 会话session的collectionName
     */
    private static final String COLLECTION_NAME_SESSION = "m_session";

    /**
     * 未回复session集合
     */
    private static final String COLLECTION_NAME_NO_REPLAY_SESSION = "m_no_replay_session";

    /**
     * 插入一条会话信息
     *
     * @param sessionInfo
     *
     * @Author He Qiang
     * @Date 2016年1月13日
     * @since 1.0.0
     */
    public void upsert(SessionDetails sessionInfo) {

        Query query = new Query(Criteria.where("sessionId").is(sessionInfo.getSessionId()));
        Update update = new Update();
        update.set("fromId", sessionInfo.getFromId());
        update.set("toId", sessionInfo.getToId());
        update.set("beginTime", sessionInfo.getBeginTime());
        update.set("endTime", sessionInfo.getEndTime());
        update.set("relation", sessionInfo.getRelation());
        update.set("payStatus", sessionInfo.getPayStatus());
        update.set("payType", sessionInfo.getPayType());
        update.set("price", sessionInfo.getPrice());
        update.set("firstMsg", sessionInfo.getFirstMsg());

        super.upsert(query, update, COLLECTION_NAME_SESSION);
    }

    /**
     * 保存冗余类信息Session对象
     * SessionDao.saveSesssion()
     *
     * @param sessionInfo
     *
     * @Author Gaoll
     * @Date 2016年8月9日
     * @since HZD-1.0.0
     */
    public void saveSesssion(SessionDetails sessionInfo) {

        super.save(sessionInfo, COLLECTION_NAME_SESSION);
    }

    /**
     * 按页码取数据
     *
     * @param sessionCondition
     *
     * @return
     *
     * @Author He Qiang
     * @Date 2016年1月13日
     * @since 1.0.0
     */
    public List<SessionDetails> pageQuery(SessionConditionVO sessionCondition) {
        // 关系取反
        int reverse = sessionCondition.getRelation() == 1 ? 0 : 1;

        Criteria criteria = new Criteria();
        // 查询条件
        if (null != sessionCondition.getFromId() && null != sessionCondition.getToId()) {
            Criteria c1 = Criteria.where("fromId").is(sessionCondition.getFromId()).and("toId").is(sessionCondition.getToId()).and("relation")
                                  .is(sessionCondition.getRelation());
            Criteria c2 = Criteria.where("fromId").is(sessionCondition.getToId()).and("toId").is(sessionCondition.getFromId()).and("relation")
                                  .is(reverse);
            criteria.orOperator(c1, c2);
        } else if (null != sessionCondition.getToId()) {
            Criteria c1 = Criteria.where("toId").is(sessionCondition.getToId()).and("relation").is(sessionCondition.getRelation());
            Criteria c2 = Criteria.where("fromId").is(sessionCondition.getToId()).and("relation").is(reverse);
            criteria.orOperator(c1, c2);
        } else if (null != sessionCondition.getFromId()) {
            Criteria c1 = Criteria.where("fromId").is(sessionCondition.getFromId()).and("relation").is(sessionCondition.getRelation());
            Criteria c2 = Criteria.where("toId").is(sessionCondition.getFromId()).and("relation").is(reverse);
            criteria.orOperator(c1, c2);
        } else if (!CollectionUtils.isEmpty(sessionCondition.getInquirerIds())) {
            // 就诊人
            criteria.and("inquirerId").in(sessionCondition.getInquirerIds());
        }

        // 是否包含病例
        if (sessionCondition.getContainRecord() != null) {
            criteria.and("containRecord").is(sessionCondition.getContainRecord());
        }

        // 处理会话状态
        if (sessionCondition.getStatus() != null) {
            // if (SessionParams.SESSION_RANGE_ALL == status.intValue()) {
            // 查询所有会话
            // } else
            if (SessionParams.SESSION_RANGE_CONSULTING == sessionCondition.getStatus()) {
                // 查询进行中会话
                criteria.and("payStatus").is(-1);
            } else if (SessionParams.SESSION_RANGE_COMPLETE == sessionCondition.getStatus()) {
                // 查询已结束回话
                criteria.and("payStatus").is(1);
            }
        }

        // 处理会话开始时间
        if (sessionCondition.getGtTime() != null && sessionCondition.getLtTime() != null) {
            criteria.and("beginTime").gt(sessionCondition.getGtTime()).lte(sessionCondition.getLtTime());
        } else if (sessionCondition.getLtTime() != null) {
            criteria.and("beginTime").lte(sessionCondition.getLtTime());
        } else if (sessionCondition.getGtTime() != null) {
            criteria.and("beginTime").gt(sessionCondition.getLtTime());
        }

        // 处理付费类型
        if (sessionCondition.getConsultPayType() != null) {
            criteria.and("consultPayType").is(sessionCondition.getConsultPayType());
        }

        // 分页查询
        return super.queryByPage(COLLECTION_NAME_SESSION, SessionDetails.class, criteria, sessionCondition.getPageNo(),
                                 sessionCondition.getPageSize(), sessionCondition.getOrderby(), sessionCondition.getOrderbyItem());
    }

    /**
     * 条数查询
     *
     * @param sessionConditionCountVO
     *
     * @return
     *
     * @Author He Qiang
     * @Date 2016年1月13日
     * @since 1.0.0
     */
    public long queryCount(SessionConditionCountVO sessionConditionCountVO) {
        // 关系取反
        int reverse = sessionConditionCountVO.getRelation() == 1 ? 0 : 1;

        Criteria criteria = new Criteria();
        // 查询条件
        if (null != sessionConditionCountVO.getFromId() && null != sessionConditionCountVO.getToId()) {
            Criteria c1 = Criteria.where("fromId")
                                  .is(sessionConditionCountVO.getFromId())
                                  .and("toId")
                                  .is(sessionConditionCountVO.getToId())
                                  .and("relation")
                                  .is(sessionConditionCountVO.getRelation());
            Criteria c2 = Criteria.where("fromId")
                                  .is(sessionConditionCountVO.getToId())
                                  .and("toId")
                                  .is(sessionConditionCountVO.getFromId())
                                  .and("relation")
                                  .is(reverse);
            criteria.orOperator(c1, c2);
        } else if (null != sessionConditionCountVO.getToId()) {
            Criteria c1 = Criteria.where("toId").is(sessionConditionCountVO.getToId()).and("relation").is(sessionConditionCountVO.getRelation());
            Criteria c2 = Criteria.where("fromId").is(sessionConditionCountVO.getToId()).and("relation").is(reverse);
            criteria.orOperator(c1, c2);
        } else if (null != sessionConditionCountVO.getFromId()) {
            Criteria c1 = Criteria.where("fromId").is(sessionConditionCountVO.getFromId()).and("relation").is(sessionConditionCountVO.getRelation());
            Criteria c2 = Criteria.where("toId").is(sessionConditionCountVO.getFromId()).and("relation").is(reverse);
            criteria.orOperator(c1, c2);
        } else if (!CollectionUtils.isEmpty(sessionConditionCountVO.getInquirerIds())) {
            // 就诊人
            criteria.and("inquirerId").in(sessionConditionCountVO.getInquirerIds());
        }

        // 是否包含病例
        if (sessionConditionCountVO.getContainRecord() != null) {
            criteria.and("containRecord").is(sessionConditionCountVO.getContainRecord());
        }

        // 处理会话状态
        if (sessionConditionCountVO.getStatus() != null) {
            // if (SessionParams.SESSION_RANGE_ALL == status.intValue()) {
            // // 查询所有会话
            // } else
            if (SessionParams.SESSION_RANGE_CONSULTING == sessionConditionCountVO.getStatus()) {
                // 查询进行中会话
                criteria.and("payStatus").is(-1);
            } else if (SessionParams.SESSION_RANGE_COMPLETE == sessionConditionCountVO.getStatus()) {
                // 查询已结束回话
                criteria.and("payStatus").is(1);
            }
        }

        // 处理会话开始时间
        if (sessionConditionCountVO.getGtTime() != null && sessionConditionCountVO.getLtTime() != null) {
            criteria.and("beginTime").gt(sessionConditionCountVO.getGtTime()).lte(sessionConditionCountVO.getLtTime());
        } else if (sessionConditionCountVO.getLtTime() != null) {
            criteria.and("beginTime").lte(sessionConditionCountVO.getLtTime());
        } else if (sessionConditionCountVO.getGtTime() != null) {
            criteria.and("beginTime").gt(sessionConditionCountVO.getLtTime());
        }

        // 处理付费类型
        if (sessionConditionCountVO.getConsultPayType() != null) {
            criteria.and("consultPayType").is(sessionConditionCountVO.getConsultPayType());
        }

        // 查询
        Query query = Query.query(criteria);

        return super.count(query, COLLECTION_NAME_SESSION);
    }

    /**
     * 更新session结束时间
     *
     * @param sessionId
     * @param endTime
     *
     * @Author He Qiang
     * @Date 2016年1月14日
     * @since 1.0.0
     */
    public void updateSession(String sessionId, Long endTime, int payStatus,
                              SessionDetails.Msg lastMsg) {
        Query query = new Query(Criteria.where("sessionId").is(sessionId));
        Update update = new Update().set("endTime", endTime).set("payStatus", payStatus)
                                    .set("lastMsg", lastMsg);

        super.updateFirst(query, update, COLLECTION_NAME_SESSION);
    }

    /**
     * 获取 session详情
     *
     * @param sessionId
     *
     * @return
     *
     * @Author He Qiang
     * @Date 2016年1月14日
     * @since 1.0.0
     */
    public SessionDetails findSessionById(String sessionId) {
        Query query = new Query(Criteria.where("sessionId").is(sessionId));
        SessionDetails session = super.findOne(query, SessionDetails.class, COLLECTION_NAME_SESSION);
        return session;
    }

    /**
     * 更新payStatus
     *
     * @param sessionId
     * @param endTime
     *
     * @Author He Qiang
     * @Date 2016年1月14日
     * @since 1.0.0
     */
    public void updatePayStatus(String sessionId, int status) {
        Query query = new Query(Criteria.where("sessionId").is(sessionId));
        Update update = new Update().set("payStatus", status);

        super.updateFirst(query, update, COLLECTION_NAME_SESSION);
    }

    /**
     * 查询出24小时未回复的医生
     *
     * @param cutOffTime
     *
     * @return
     *
     * @Author He Qiang
     * @Date 2016年1月19日
     * @since 1.0.0
     */
    public List<SessionDetails> findSessionByTime(Long beginTime) {
        Criteria c1 = Criteria.where("beginTime").lt(beginTime).and("endTime").is(0L);
        Query query = new Query(c1).with(Sort.by(Direction.ASC, "beginTime"));
        return super.find(query, SessionDetails.class, COLLECTION_NAME_SESSION);
    }

    /**
     * 获取会话列表（beginTime区间）
     * SessionDao.findSessionByTime()
     *
     * @param fromId
     * @param toId
     * @param relation
     * @param ltTime
     * @param gtTime
     * @param pageNo
     * @param pageSize
     *
     * @return
     *
     * @Date 2016年6月17日
     * @since 2.5.0
     */
    public List<SessionDetails> findSessionByTime(Long fromId, Long toId, int relation, Long ltTime,
                                                  Long gtTime, int pageNo, int pageSize) {

        // 关系取反
        int reverse = relation == 1 ? 0 : 1;

        // 查询条件
        Criteria c1 = Criteria.where("fromId").is(fromId).and("toId").is(toId).and("relation")
                              .is(relation);
        Criteria c2 = Criteria.where("fromId").is(toId).and("toId").is(fromId).and("relation")
                              .is(reverse);

        Criteria criteria = new Criteria().orOperator(c1, c2);
        if (null != ltTime && null != gtTime) {
            criteria = criteria.and("beginTime").gt(gtTime).lte(ltTime);
        } else if (null != gtTime) {
            criteria = criteria.and("beginTime").gt(gtTime);
        } else if (null != ltTime) {
            criteria = criteria.and("beginTime").lte(ltTime);
        }
        Query query = new Query(criteria).with(Sort.by(Direction.DESC, "beginTime"));

        return super.find(query, SessionDetails.class, COLLECTION_NAME_SESSION);

    }

    /**
     * SessionDao.updateContains()
     *
     * @param sessionId
     * @param recomFlag
     * @param containVideo
     *
     * @Author Gaoll
     * @Date 2016年8月9日
     * @since HZD-1.0.0
     */
    public void updateContains(String sessionId, boolean recomFlag, boolean recordFlag) {

        // 变更session属性containRecom、containVideo属性
        if (StringUtils.isBlank(sessionId) || (!recomFlag && !recordFlag)) {
            return;
        }
        Query query = new Query(Criteria.where("sessionId").is(sessionId));
        Update update = new Update();
        if (recomFlag) {
            update.set("containRecom", SessionDetails.CONTAIN_RECOM_YES);
        }
        if (recordFlag) {
            update.set("containRecord", SessionDetails.CONTAIN_RECORD_YES);
        }

        super.updateFirst(query, update, COLLECTION_NAME_SESSION);
    }

    /**
     * 根据sessionid集合查询
     *
     * @param sessionId
     * @return
     */
    public List<SessionDetails> findSessionByIdIn(List<String> sessionIds) {
        Query query = new Query(Criteria.where("sessionId").in(sessionIds));

        return super.find(query, SessionDetails.class, COLLECTION_NAME_SESSION);
    }

    /**
     * 更新session的firstMsg
     *
     * @param sessionId
     * @param firstMsg
     *
     * @Author luao
     */
    public void updateFirstMsg(String sessionId, SessionDetails.Msg firstMsg) {
        Query query = new Query(Criteria.where("sessionId").is(sessionId));
        Update update = new Update().set("firstMsg", firstMsg);

        super.updateFirst(query, update, COLLECTION_NAME_SESSION);
    }
}
